const path = require('path')
const webpack = require('webpack')
const TerserPlugin = require('terser-webpack-plugin')
const CopyPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

const { pages } = require('./src/pages.config.js')

module.exports = (env, argv) => {
  const devMode = !!env.WEBPACK_SERVE

  return {
    mode: argv.mode || (devMode ? 'development' : 'production'),
    entry: Object.fromEntries(pages.map((page) => [page.chunk, page.script])),
    output: {
      publicPath: '/',
      path: path.resolve(__dirname, 'dist'),
      filename: devMode ? '[name].js' : '[name].[contenthash:12].js',
      assetModuleFilename: devMode ? '[file][query]' : '[hash][ext][query]',
      environment: {
        arrowFunction: false,
        const: false,
        destructuring: false,
        forOf: false
      },
      clean: true
    },
    module: {
      rules: [
        {
          test: /\.pug$/,
          use: ['babel-loader', 'pug-loader']
        },
        {
          test: /\.(png|jpg|webp)$/,
          type: 'asset'
        },
        {
          test: /\.htc$/,
          type: 'asset/resource'
        },
        {
          test: /\.js$/,
          use: 'babel-loader',
          exclude: /node_modules/
        },
        {
          test: /\.js$/,
          use: 'babel-loader',
          include: [
            path.resolve(__dirname, 'node_modules/resize-observer-polyfill'),
            path.resolve(__dirname, 'node_modules/preact')
          ]
        },
        {
          test: /\.tsx?$/,
          use: ['babel-loader', 'ts-loader'],
          exclude: /node_modules/
        },
        {
          test: /\.s?css$/,
          use: [
            devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
            {
              loader: 'css-loader',
              options: {
                importLoaders: 2
              }
            },
            'postcss-loader',
            'sass-loader'
          ],
          exclude: /\.module\.s?css$/
        },
        {
          test: /\.s?css$/,
          use: [
            devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
            {
              loader: 'css-loader',
              options: {
                importLoaders: 2,
                modules: true
              }
            },
            'postcss-loader',
            'sass-loader'
          ],
          include: /\.module\.s?css$/
        }
      ]
    },
    plugins: [
      new CopyPlugin({
        patterns: [{ from: 'static', to: 'static' }]
      }),
      new webpack.DefinePlugin({
        'process.env.SERVICE_URL': JSON.stringify('/api')
      }),
      !devMode &&
        new MiniCssExtractPlugin({
          filename: '[name].[contenthash:12].css'
        })
    ]
      .concat(
        pages.map((page) => {
          return new HtmlWebpackPlugin({
            filename: page.filename,
            template: page.template,
            chunks: [page.chunk]
          })
        })
      )
      .filter(Boolean),
    resolve: {
      alias: {
        '@': path.resolve(__dirname, 'src')
      },
      extensions: ['.tsx', '.ts', '.js']
    },
    devServer: {
      port: 9000,
      // devMiddleware: {
      //   index: 'index.html'
      // },
      hot: true,
      client: { logging: 'error' },
      proxy: {
        '/api': {
          target: 'https://api.example.com',
          headers: {
            host: 'api.example.com',
            origin: 'https://api.example.com'
          },
          secure: false
        }
      }
    },
    devtool: devMode ? 'eval-cheap-source-map' : 'source-map',
    optimization: {
      minimize: !devMode,
      minimizer: [
        new TerserPlugin({
          terserOptions: {
            compress: {
              hoist_vars: true // IE8, IE9
            },
            ie8: true
          },
          exclude: /static/
        })
      ],
      runtimeChunk: 'single',
      splitChunks: {
        cacheGroups: {
          vendor: {
            test: /[\\/]node_modules[\\/]/,
            name: 'vendors',
            chunks: 'all'
          }
        }
      }
    },
    performance: {
      assetFilter: function (assetFilename) {
        return !/static/.test(assetFilename) && assetFilename.endsWith('.js')
      }
    }
  }
}
